package com.duojuhe.interceptor;

import com.duojuhe.cache.LoginUserTokenCache;
import com.duojuhe.cache.SystemSafeRefererCache;
import com.duojuhe.common.bean.UserTokenInfoVo;
import com.duojuhe.common.constant.SystemConstants;
import com.duojuhe.common.exception.base.DuoJuHeException;
import com.duojuhe.common.result.ErrorCodes;
import com.duojuhe.common.utils.jwt.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

@Slf4j
@Component
public class SecurityInterceptor implements HandlerInterceptor {
    @Resource
    private LoginUserTokenCache loginUserTokenCache;
    @Resource
    private SystemSafeRefererCache systemSafeRefererCache;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 跨域时会首先发送一个option请求，这里我们给option请求直接返回正常状态
        if (RequestMethod.OPTIONS.name().equals(request.getMethod().toUpperCase())) {
            response.setStatus(HttpStatus.OK.value());
            return false;
        }
        //验证白名单
        if (!checkRefererList(request)) {
            clearUserToken();
            throw new DuoJuHeException(ErrorCodes.KICK_OUT_ERROR);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }

    /**
     * 清除用户登录token
     */
    private void clearUserToken() {
        //获取当前登录人
        UserTokenInfoVo currentUser = LoginUserTokenCache.getCurrentLoginUserInfoDTO();
        if (!SystemConstants.UNKNOWN_ID.equals(currentUser.getUserId())) {
            loginUserTokenCache.delUserTokenInfoVoCacheByToken(currentUser.getToken());
        }
    }

    /**
     * 验证请求头安全key
     *
     * @param request
     * @return
     */
    private boolean checkDjhSafeKey(HttpServletRequest request) {
        //获取请求头上的安全key标识
        String djhSafeKey = request.getHeader(SystemConstants.DJH_SAFE_KEY);
        if (StringUtils.isEmpty(djhSafeKey)) {
            return false;
        }
        return JwtUtils.verify(djhSafeKey);
    }

    /**
     * 校验系统安全白名单
     *
     * @param request
     * @return
     */
    private boolean checkRefererList(HttpServletRequest request) {
        //获取请求头上的标识
        String referer = request.getHeader("referer");
        if (StringUtils.isEmpty(referer)) {
            return false;
        }
        //获取请求接口
        String reqUrl = request.getRequestURI();
        //当前服务
        String serverName = request.getServerName();
        log.debug("当前请求serverName：{}，reqUrl：{}，referer：{}", serverName, reqUrl, referer);
        //获取白名单内的集合数据
        List<String> allowRefererList = systemSafeRefererCache.getAllowRefererListCache();
        if (allowRefererList.isEmpty()) {
            return true;
        }
        //去除末尾的斜杆
        referer = referer.replaceAll("/$", "");
        //查询是否配置了允许请求
        return allowRefererList.contains(referer.toLowerCase());
    }
}
